﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace LightEngine
{
    namespace Utilities
    {
        namespace FileSystem
        {
            /// <WIN32 структура данных internal struct _FILETIME>
            /// Предназначена для хранения системного времени в 2х 32-разрядных беззнаковых 
            /// целочичисленных переменных dwLowDateTime и dwHighDateTime.
            /// </WIN32 структура данных internal struct _FILETIME>
            [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0)]
            internal struct _FILETIME
            {
                public uint dwLowDateTime;
                public uint dwHighDateTime;
            }

            /// <WIN32 структура данных internal struct _WIN32_FIND_DATAW>
            /// Структура данных, хранящая атрибуты файла, размер, время создания,
            /// время последнего доступа и время последнего изменения.
            /// </WIN32 структура данных internal struct _WIN32_FIND_DATAW>
            [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0, CharSet = CharSet.Unicode)]
            internal struct _WIN32_FIND_DATAW
            {
                public uint dwFileAttributes;
                public _FILETIME ftCreationTime;
                public _FILETIME ftLastAccessTime;
                public _FILETIME ftLastWriteTime;
                public uint nFileSizeHigh;
                public uint nFileSizeLow;
                public uint dwReserved0;
                public uint dwReserved1;

                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
                public string cFileName;

                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
                public string cAlternateFileName;
            }

            /// <Описание COM-интерфейса IShellLinkW> 
            ///  Интерфейс содержит функции для создания/изменения/получения атрибутов ярлыков
            ///  Элементы интерфейса:
            ///  1. Методы (функции-члены):
            ///  а) [PreserveSig()]int GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszFile,
            ///                                int cchMaxPath, ref _WIN32_FIND_DATAW pfd, uint fFlags)
            ///     Функция для получения пути и имени файла shell link объекта (ярлыка).
            ///  б) [PreserveSig()]int GetIDList(out IntPtr ppidl); Получение списка идентификаторов в
            ///     ppidl Shell link объектов (ярлыков).
            ///  в) [PreserveSig()]int SetIDList(IntPtr pidl); Устанавливает указатель на список 
            ///     идентификаторов pidl Shell link объектов (ярлыков).
            ///  г) [PreserveSig()]int GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
            ///                                       int cchMaxName); 
            ///     получение описание Shell Link объекта.
            ///  д) [PreserveSig()]int SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); 
            ///     задание описания Shell Link объекта.
            ///  е) [PreserveSig()]int GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszDir,
            ///                                            int cchMaxPath);
            ///     получение директории Shell Link Объекта.
            ///  ж) [PreserveSig()]int SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
            ///     установка директории для Shell Link объекта.
            ///  з) [PreserveSig()]int GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszArgs,
            ///                                     int cchMaxPath);
            ///     получение аргументов коммандной строки Shell Link объекта.
            ///  и) [PreserveSig()]int SetArguments( [MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
            ///     задание аргументов коммандной строки Shell Link объекта.
            ///  к) [PreserveSig()]int GetHotkey(out ushort pwHotkey); получение горячей клавиши для 
            ///     Shell Link объекта.
            ///  л) [PreserveSig()]int SetHotkey(out ushort pwHotkey); установка горячей клавиши для 
            ///     Shell Link объекта.
            ///  м) [PreserveSig()]int GetShowCmd(out uint piShowCmd); получение/установка отображения 
            ///     показа команд командной строки.
            ///  н) [PreserveSig()]int SetShowCmd(out uint piShowCmd); получение/установка отображения 
            ///     показа команд командной строки.
            ///  о) [PreserveSig()]int GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszIconPath,
            ///                                        int cchIconPath,out int piIcon);
            ///     получение индекса и директории Shell Link пиктограммы.
            ///  п) [PreserveSig()]int SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath,
            ///                                        int iIcon);
            ///     установка индекса и директории Shell Link пиктограммы.
            ///  р) [PreserveSig()]int SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
            ///                                        uint dwReserved);
            ///     установка относительного пути Shell Link объекта.
            ///  с) [PreserveSig()]int Resolve( IntPtr hWnd, uint fFlags); получение Shell Link объекта и 
            ///     обновление списка его идентификаторов.
            ///  т) [PreserveSig()]int SetPath([MarshalAs(UnmanagedType.LPWStr)]string pszFile); установка
            ///     пути и имени Shell Link объекта.
            /// </Описание интерфейса ISpectrumLoadInterface>
            [ComImport, Guid("000214F9-0000-0000-C000-000000000046"),
             InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            interface IShellLinkW
            {
                [PreserveSig()]
                int GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
                            int cchMaxPath, ref _WIN32_FIND_DATAW pfd, uint fFlags);

                [PreserveSig()]
                int GetIDList(out IntPtr ppidl);
                [PreserveSig()]
                int SetIDList(IntPtr pidl);

                [PreserveSig()]
                int GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
                                   int cchMaxName);
                [PreserveSig()]
                int SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);

                [PreserveSig()]
                int GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszDir,
                                        int cchMaxPath);
                [PreserveSig()]
                int SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);

                [PreserveSig()]
                int GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszArgs,
                                 int cchMaxPath);
                [PreserveSig()]
                int SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);

                [PreserveSig()]
                int GetHotkey(out ushort pwHotkey);
                [PreserveSig()]
                int SetHotkey(ushort pwHotkey);

                [PreserveSig()]
                int GetShowCmd(out uint piShowCmd);
                [PreserveSig()]
                int SetShowCmd(uint piShowCmd);

                [PreserveSig()]
                int GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszIconPath,
                                    int cchIconPath, out int piIcon);
                [PreserveSig()]
                int SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);

                [PreserveSig()]
                int SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);

                [PreserveSig()]
                int Resolve(IntPtr hWnd, uint fFlags);

                [PreserveSig()]
                int SetPath([MarshalAs(UnmanagedType.LPWStr)]string pszFile);
            }

            /// <Описание класса internal class ShellLinkClass> 
            ///  Пустой класс для доступа к COM-интерфейсу IShellLinkW
            /// </Описание класса internal class ShellLinkClass>
            [ComImport, Guid("00021401-0000-0000-C000-000000000046")]
            internal class ShellLinkClass
            {

            }

            /// <Описание COM-интерфейса IPersistFile> 
            ///  Интерфейс содержит функции для создания/изменения/получения атрибутов ярлыков
            ///  Элементы интерфейса:
            ///  1. Методы (функции-члены):
            ///  а) [PreserveSig()] int GetClassID(out Guid pClassID); получение CLSID объекта.
            ///  б) [PreserveSig()]int IsDirty(); проверка изменений относительно поледнего 
            ///     момента изменения файла
            ///  в) [PreserveSig()]int Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
            ///                              uint dwMode);
            ///     загрузка файла с диска и инициализациия объекта содержимым файла.
            ///  г) [PreserveSig()]int Save([MarshalAs(UnmanagedType.LPWStr)]string pszFileName,
            ///                             [MarshalAs(UnmanagedType.Bool)]bool fRemember);
            ///     сохранение объекта в определенный файл.
            ///  д) [PreserveSig()]int SaveCompleted([MarshalAs(UnmanagedType.LPWStr)]string pszFileName);
            ///     уведомление объекта об успешном сохранении его в файл.
            ///  е) [PreserveSig()]int GetCurFile([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszIconPath);
            ///     получение полного имени связанного с объектом файла.
            /// </Описание COM-интерфейса IPersistFile>
            [ComImport()]
            [Guid("0000010B-0000-0000-C000-000000000046")]
            [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            internal interface IPersistFile
            {
                [PreserveSig()]
                int GetClassID(out Guid pClassID);

                [PreserveSig()]
                int IsDirty();

                [PreserveSig()]
                int Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
                         uint dwMode);
                [PreserveSig()]
                int Save([MarshalAs(UnmanagedType.LPWStr)]string pszFileName,
                         [MarshalAs(UnmanagedType.Bool)]bool fRemember);

                [PreserveSig()]
                int SaveCompleted([MarshalAs(UnmanagedType.LPWStr)]string pszFileName);

                [PreserveSig()]
                int GetCurFile([Out(), MarshalAs(UnmanagedType.LPWStr)]StringBuilder pszIconPath);
            }

            /// <описание класса public class COMShortCuts>
            /// Версия класса 1.0
            /// Автор(ы): Ушаков Михаил
            /// Класс предназначен для хранения истории результатов преобразования Мессбауэровских спектров
            /// и извлечения любого элемента истории (спектра).
            /// Элементы класса:
            /// 1. Константы класса:
            ///    отсутствуют.
            /// 2. Поля класса:
            /// а) private ShellLinkClass LinkClass; класс для получения доступа к интерфейсу Link.
            /// б) private IShellLinkW Link; COM-интерфейс IShellLink.
            /// 3. Методы класса:
            /// а) public void DeleteShortCut(String ShortcutPath, String ShortcutName) функция выполняет
            ///    удаление Shell Link объекта (ярлыка) расположенного в ShortcutPath с именем ShortcutName.
            /// б) public Boolean IsShortCutExist(String ShortcutPath, String ShortcutName) функция проверяет
            ///    существует ли ярлык с именем ShortcutName в ShortcutPath если да, то возвращает true,
            ///    иначе false.
            /// в) public Boolean CreateShortCut(String AppExecutableFile, String ShortcutPath,
            ///                                  String ShortcutName, String Description);
            ///    функция создает ярлык приложения AppExecutableFile (полный путь до исполняемого файла)
            ///    в ShortcutPath с именем ShortcutName и с описанием Description, если создать ярлык
            ///    удалось возвращает true, иначе false.
            /// 4. Свойства и индексаторы класса:
            ///    отсутсвуют.
            /// </описание класса public class COMShortCuts>
            public class COMShortCuts
            {
                private ShellLinkClass LinkClass;
                private IShellLinkW Link;

                public COMShortCuts()
                {
                    // Получение зарегестрированного COM-класса
                    LinkClass = new ShellLinkClass();
                }

                public void DeleteShortCut(String ShortcutPath, String ShortcutName)
                {
                    StringBuilder LnkFullPath = new StringBuilder();
                    LnkFullPath.Insert(LnkFullPath.Length, ShortcutPath);
                    if (LnkFullPath[LnkFullPath.Length - 1] != '\\')
                        LnkFullPath.Insert(LnkFullPath.Length, '\\');
                    LnkFullPath.Insert(LnkFullPath.Length, ShortcutName + ".lnk");
                    if (File.Exists(LnkFullPath.ToString()) == true)
                        File.Delete(LnkFullPath.ToString());
                }

                public Boolean IsShortCutExist(String ShortcutPath, String ShortcutName)
                {
                    StringBuilder LnkFullPath = new StringBuilder();
                    LnkFullPath.Insert(LnkFullPath.Length, ShortcutPath);
                    if (LnkFullPath[LnkFullPath.Length - 1] != '\\')
                        LnkFullPath.Insert(LnkFullPath.Length, '\\');
                    LnkFullPath.Insert(LnkFullPath.Length, ShortcutName + ".lnk");
                    if (File.Exists(LnkFullPath.ToString()) == true)
                        return true;
                    return false;
                }

                public Boolean CreateShortCut(String AppExecutableFile,
                                              String ShortcutPath,
                                              String ShortcutName,
                                              String Description)
                {
                    try
                    {
                        IPersistFile FileIOInt;
                        // Получение COM-интерфейса IShellLink
                        Link = (IShellLinkW)LinkClass;
                        Link.SetPath(AppExecutableFile);
                        Link.SetDescription(Description);

                        StringBuilder LnkFullPath = new StringBuilder();
                        LnkFullPath.Insert(LnkFullPath.Length, ShortcutPath);
                        if (LnkFullPath[LnkFullPath.Length - 1] != '\\')
                            LnkFullPath.Insert(LnkFullPath.Length, '\\');
                        LnkFullPath.Insert(LnkFullPath.Length, ShortcutName + ".lnk");
                        // Получение COM-интерфейса IPersistFile
                        FileIOInt = (IPersistFile)Link;
                        FileIOInt.Save(LnkFullPath.ToString(), false);

                        return true;
                    }
                    catch (Exception Except)
                    {
                        Except.ToString();
                        return false;
                    }
                }
            }
        }
    }
}
